home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / system / source / cpuaccel.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-02-28  |  5.3 KB  |  216 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #include "stdafx.h"
  27. #include <wtypes.h>
  28. #include <winnt.h>
  29. #include <vd2/system/cpuaccel.h>
  30.  
  31. static long g_lCPUExtensionsEnabled;
  32. static long g_lCPUExtensionsAvailable;
  33.  
  34. extern "C" {
  35.     bool FPU_enabled, MMX_enabled, SSE_enabled, ISSE_enabled, SSE2_enabled;
  36. };
  37.  
  38.  
  39. #ifdef _M_AMD64
  40.  
  41.     long CPUCheckForExtensions() {
  42.         long flags = CPUF_SUPPORTS_FPU;
  43.  
  44.         if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
  45.             flags |= CPUF_SUPPORTS_MMX;
  46.  
  47.         if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE))
  48.             flags |= CPUF_SUPPORTS_SSE | CPUF_SUPPORTS_INTEGER_SSE;
  49.  
  50.         if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE))
  51.             flags |= CPUF_SUPPORTS_SSE2;
  52.  
  53.         if (IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE))
  54.             flags |= CPUF_SUPPORTS_3DNOW;
  55.  
  56.         return flags;
  57.     }
  58.  
  59. #else
  60.  
  61.     // This is ridiculous.
  62.  
  63.     static long CPUCheckForSSESupport() {
  64.         __try {
  65.     //        __asm andps xmm0,xmm0
  66.  
  67.             __asm _emit 0x0f
  68.             __asm _emit 0x54
  69.             __asm _emit 0xc0
  70.  
  71.         } __except(EXCEPTION_EXECUTE_HANDLER) {
  72.             if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
  73.                 g_lCPUExtensionsAvailable &= ~(CPUF_SUPPORTS_SSE|CPUF_SUPPORTS_SSE2|CPUF_SUPPORTS_SSE3|CPUF_SUPPORTS_SSSE3);
  74.         }
  75.  
  76.         return g_lCPUExtensionsAvailable;
  77.     }
  78.  
  79.     long __declspec(naked) CPUCheckForExtensions() {
  80.         __asm {
  81.             push    ebp
  82.             push    edi
  83.             push    esi
  84.             push    ebx
  85.  
  86.             xor        ebp,ebp            ;cpu flags - if we don't have CPUID, we probably
  87.                                     ;won't want to try FPU optimizations.
  88.  
  89.             ;check for CPUID.
  90.  
  91.             pushfd                    ;flags -> EAX
  92.             pop        eax
  93.             or        eax,00200000h    ;set the ID bit
  94.             push    eax                ;EAX -> flags
  95.             popfd
  96.             pushfd                    ;flags -> EAX
  97.             pop        eax
  98.             and        eax,00200000h    ;ID bit set?
  99.             jz        done            ;nope...
  100.  
  101.             ;CPUID exists, check for features register.
  102.  
  103.             mov        ebp,00000003h
  104.             xor        eax,eax
  105.             cpuid
  106.             or        eax,eax
  107.             jz        done            ;no features register?!?
  108.  
  109.             ;features register exists, look for MMX, SSE, SSE2.
  110.  
  111.             mov        eax,1
  112.             cpuid
  113.             mov        ebx,edx
  114.             and        ebx,00800000h    ;MMX is bit 23 of EDX
  115.             shr        ebx,21
  116.             or        ebp,ebx            ;set bit 2 if MMX exists
  117.  
  118.             mov        ebx,edx
  119.             and        edx,02000000h    ;SSE is bit 25 of EDX
  120.             shr        edx,25
  121.             neg        edx
  122.             and        edx,00000018h    ;set bits 3 and 4 if SSE exists
  123.             or        ebp,edx
  124.  
  125.             and        ebx,04000000h    ;SSE2 is bit 26 of EDX
  126.             shr        ebx,21
  127.             and        ebx,00000020h    ;set bit 5
  128.             or        ebp,ebx
  129.  
  130.             test    ecx, 1            ;SSE3 is bit 0 of ECX
  131.             jz        no_sse3
  132.             or        ebp, 100h
  133. no_sse3:
  134.  
  135.             test    ecx, 200h        ;SSSE3 is bit 9 of ECX
  136.             jz        no_ssse3
  137.             or        ebp, 200h
  138. no_ssse3:
  139.  
  140.             ;check for vendor feature register (K6/Athlon).
  141.  
  142.             mov        eax,80000000h
  143.             cpuid
  144.             mov        ecx,80000001h
  145.             cmp        eax,ecx
  146.             jb        done
  147.  
  148.             ;vendor feature register exists, look for 3DNow! and Athlon extensions
  149.  
  150.             mov        eax,ecx
  151.             cpuid
  152.  
  153.             mov        eax,edx
  154.             and        edx,80000000h    ;3DNow! is bit 31
  155.             shr        edx,25
  156.             or        ebp,edx            ;set bit 6
  157.  
  158.             mov        edx,eax
  159.             and        eax,40000000h    ;3DNow!2 is bit 30
  160.             shr        eax,23
  161.             or        ebp,eax            ;set bit 7
  162.  
  163.             and        edx,00400000h    ;AMD MMX extensions (integer SSE) is bit 22
  164.             shr        edx,19
  165.             or        ebp,edx
  166.  
  167.     done:
  168.             mov        eax,ebp
  169.             mov        g_lCPUExtensionsAvailable, ebp
  170.  
  171.             ;Full SSE and SSE-2 require OS support for the xmm* registers.
  172.  
  173.             test    eax,00000030h
  174.             jz        nocheck
  175.             call    CPUCheckForSSESupport
  176.     nocheck:
  177.             pop        ebx
  178.             pop        esi
  179.             pop        edi
  180.             pop        ebp
  181.             ret
  182.         }
  183.     }
  184.  
  185. #endif
  186.  
  187. long CPUEnableExtensions(long lEnableFlags) {
  188.     g_lCPUExtensionsEnabled = lEnableFlags;
  189.  
  190.     MMX_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_MMX);
  191.     FPU_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_FPU);
  192.     SSE_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_SSE);
  193.     ISSE_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_INTEGER_SSE);
  194.     SSE2_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_SSE2);
  195.  
  196.     return g_lCPUExtensionsEnabled;
  197. }
  198.  
  199. long CPUGetAvailableExtensions() {
  200.     return g_lCPUExtensionsAvailable;
  201. }
  202.  
  203. long CPUGetEnabledExtensions() {
  204.     return g_lCPUExtensionsEnabled;
  205. }
  206.  
  207. void VDCPUCleanupExtensions() {
  208. #ifndef _M_AMD64
  209.     if (ISSE_enabled)
  210.         __asm sfence
  211.     if (MMX_enabled)
  212.         __asm emms
  213. #else
  214.     _mm_sfence();
  215. #endif
  216. }